// 1: node cluster 采用了哪种集群方式
//  - 1 个node 实例开启多个端口，通过反向代理服务器向各个端口进行转发
        // 暂用多个端口， 多进程之间进行进程间通讯比较麻烦
//  - 1 个 node 实例开启多进程监听同一个端口， 通过负载均衡分配请求(Master -> Worker)
        // 要保证服务器的稳定性， 需要对 Master 要求比较高；

// 在 nodejs 中采用的是第二种方案；

// master
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

console.log(1111);

// RR 轮询算法
cluster.schedulingPolicy = cluster.SCHED_RR
// 策略二： 由操作系统来调度
cluster.schedulingPolicy = cluster.SCHED_NONE
// 或者是 NODE_CLUSTER_SCHED_POLICY 这个环境变量的值来设置（rr ||none）

if (cluster.isMaster) {
	console.log(`Master 进程 ${process.pid} 正在运行`);

  console.log("numCPUs: ", numCPUs);
  for (let i = 0; i < numCPUs; i++) { // 衍生工作进程。
    // fork() 其本质还是通过了 child_process.fork() 方法来创建的； 这个怎么实现进程间的通讯呢？？？？
    cluster.fork(); // 开启 worker 进程, 当开启一个 worker 进程； 会运行当前文件

    // 那么就是 Master 创建了一个 socket 并绑定了监听到了该端口，通过与子进程之间建立了 IPC 通讯，
    // 通过调用子进程的 send 方法将socket 句柄传递过去
	}

  cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} 已退出`) });
} else {
  // 多个进程监听同一个端口，
  // 通过命令查看监听的端口： lsof -i -P -n | grep 9000,
  // 查看进程
  http.createServer((req, res) => res.end(`你好世界 ${process.pid}`)).listen(9000);
  console.log(`主进程${process.ppid} --- Worker 进程 ${process.pid} 已启动`);
}

// Master 进程退出之后，Worker 进程会自动退出 cluster 模块中内部会处理退出
// 使用 child_process.fork() 出来的子进程，master 进程退出了、子进程不做处理，
// 那么子进程会被 init 进程收养，成为孤儿进程